package com.example.simple_file_chooser;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.TextUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;


/***
 * 生命周期必须管理
 * 否则 二次发送无效
 */
public class BroadcastBuilder extends AndroidInstance {

    static Map namecontextmap = new TreeMap();
    static final MapBuilder mapBuilder = MapBuilder.build();
    private FunCallback frontfunCallback;

    public static BroadcastBuilder build() {
        return new BroadcastBuilder();
    }


    public static Map<String, BroadcastReceiver> casts = new TreeMap<String, BroadcastReceiver>();

    public String placename;

    public BroadcastBuilder place(String placename) {
        this.placename = placename;
        return this;
    }

    public void receiveOut(final String name, final String task, final Context context, final FunCallback fck) {
        receive(name + "_out", task, context, fck);
    }

    public void receive(final String name, final String task, final Context context, final FunCallback fck) {
        if (!TextUtils.isEmpty(placename)) {
            if (!namecontextmap.containsKey(placename)) {
                namecontextmap.put(placename, new ArrayList());
            }
            ((ArrayList) namecontextmap.get(placename)).add(name);
        }

//task == null router
        if (task != null) {
            if (!mapBuilder.get().containsKey(name)) {
                mapBuilder.add(name, MapBuilder.build().add(task, fck));
            }
            MapBuilder lb = ((MapBuilder) mapBuilder.get().get(name));
            if (lb != null && !lb.get().containsKey(task)) {
                lb.add(task, fck);
            }
        }
        BroadcastReceiver br = null;
//        if (casts.containsKey(name)) {
//            try {
//                getContext().unregisterReceiver(br);
//            } catch (Exception e) {
//
//            }
//            casts.remove(name);
//        }

        try {
            if (!casts.containsKey(name)) {
                br = register(name, context, fck);
                casts.put(name, br);
            }
        } catch (Exception e) {
            getContext().unregisterReceiver(br);
//            casts.remove(name);
            br = register(name, context, fck);
            casts.put(name, br);
        }
    }

    private BroadcastReceiver register(final String name, Context context, final FunCallback fck) {
        BroadcastReceiver br;
        context.registerReceiver(br = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String intenttask = intent.getStringExtra("task");
                try {
                    if (intenttask == null) {
                        if (fck != null) {
                            fck.onCallback(context, intent);
                            fck.simpleRun(intent);
                        }
                    } else {
                        MapBuilder lb = (MapBuilder) mapBuilder.get().get(name);
                        if (lb == null) {
                            if (fck != null) {
                                fck.onCallback(context, intent);
                                fck.simpleRun(intent);
                            }
                        } else {
                            if (lb.get().containsKey(intenttask)) {
                                FunCallback funCallback = (FunCallback) lb.get().get(intenttask);
                                if (funCallback != null) {
                                    funCallback.onCallback(context, intent);
                                    funCallback.simpleRun(intent);
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
//                    CrashHandler.errorDialog(e);
                }
            }
        }, new IntentFilter(name));
        return br;
    }


    @Override
    public AndroidInstance use(Object mp, Object... p) {
        return null;
    }

    public static enum Starttype {
        Activity, broadcast, service, contentprovider
    }


    Map item;

    public BroadcastBuilder setDataItem(Map item) {
        this.item = item;
        return this;
    }


    public Map intentMap = new TreeMap();

    public BroadcastBuilder setIntentMap(Map intentMap) {
        this.intentMap = intentMap;
        return this;
    }

    private String uri;
    private MapBuilder map;
    private Starttype statrttype;
    private FunCallback backfunCallback;

    public BroadcastBuilder setUri(String uri) {
        this.uri = uri;
        return this;
    }

    public BroadcastBuilder setMap(MapBuilder map) {
        this.map = map;
        return this;
    }

    public BroadcastBuilder setStatrttype(Starttype statrttype) {
        this.statrttype = statrttype;
        return this;
    }

    public BroadcastBuilder setBackfunCallback(FunCallback backfunCallback) {
        this.backfunCallback = backfunCallback;
        return this;
    }

    public BroadcastBuilder setFrontfunCallback(FunCallback frontfunCallback) {
        this.frontfunCallback = frontfunCallback;

        return this;
    }

    public String location;

    public String getLocation() {
        return location;
    }

    public BroadcastBuilder setLocation(String location) {
        this.location = location;
        return this;
    }

    public void registerSend() {
        String location = "";
        String task = "";
        if (uri.contains("-")) {
            location = uri.split("-")[0];
            task = uri.split("-")[1];
        } else {
            location = uri;
        }
        setLocation(location);
        Context context = getContext();
        MapBuilder mb = map;
        Starttype starttype = statrttype;
        FunCallback funcallback = backfunCallback;
        mb = mb == null ? MapBuilder.build() : mb;
        if (frontfunCallback != null) {
            try {
                receive(location + "front", "", context, frontfunCallback);
            } catch (Exception e) {
                remove(location + "front", context);
                receive(location + "front", "", context, frontfunCallback);

            }
        }
        try {
            receive(location + "back", "", context, funcallback);
        } catch (Exception e) {
            remove(location + "back", context);
            receive(location + "back", "", context, funcallback);
        }
        sendAction(location + "front", "", context, mb, starttype);
    }


    public void registerSend(String location, String task, Context context, MapBuilder mb, Starttype starttype, FunCallback funcallback) {
        mb = mb == null ? MapBuilder.build() : mb;
        receive(location + "", task, context, funcallback);
        sendAction(location, task, context, mb, starttype);
    }

    public void sendAction(String funcname, Context context, MapBuilder mb, Starttype starttype) {
        sendAction(funcname, "", context, mb, starttype);
    }

    public void sendAction(String funcname, String task, Context context, MapBuilder mb, Starttype starttype) {
        Intent in = new Intent(funcname);
        if (mb != null && mb.get() != null && mb.get().size() > 0) {

            for (Object o : mb.get().keySet()) {
                if (o == null || mb.get().get(o) == null) {
                    continue;
                }
                in.putExtra(o.toString(), mb.get().get(o).toString());
            }
        } else {
            mb = MapBuilder.build();
        }
        task = TextUtils.isEmpty(task) ? "" : task;

        if (mb.get().size() > 0) {
            in
                    .putExtra("params", (Serializable) mb.get());
        }
        in
                .putExtra("task", task);

        in.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        switch (starttype) {
            case Activity:
                context.startActivity(in);
                break;
            case broadcast:
                context.sendBroadcast(in);
                break;
        }
//        if (!TextUtils.isEmpty(task)) {
//            sendAction(funcname, "", context, mb, starttype);
//        }
    }
//android.os.Parcel.writeValue(Parcel.java:1772)
//            android.os.Parcel.writeMapInternal(Parcel.java:812)
//            android.os.Parcel.writeMap(Parcel.java:796)
//            android.os.Parcel.writeValue(Parcel.java:1684)
//            android.os.Parcel.writeList(Parcel.java:926)
//            android.os.Parcel.writeValue(Parcel.java:1719)
//            android.os.Parcel.writeMapInternal(Parcel.java:812)
//            android.os.Parcel.writeMap(Parcel.java:796)
//            android.os.Parcel.writeValue(Parcel.java:1684)
//            android.os.Parcel.writeArrayMapInternal(Parcel.java:838)
//            android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1542)
//            android.os.Bundle.writeToParcel(Bundle.java:1232)
//            android.os.Parcel.writeBundle(Parcel.java:878)
//            android.content.Intent.writeToParcel(Intent.java:9599)
//            android.app.IActivityManager$Stub$Proxy.broadcastIntent(IActivityManager.java:4462)
//            android.app.ContextImpl.sendBroadcast(ContextImpl.java:970)
//            android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:437)
//            android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:437)
//            app.auto.runner.base.BroadcastBuilder.sendAction(BroadcastBuilder.java:276)
//            cn.bmob.test.BmobData$1$1.onCallback(BmobData.java:67)
//            cn.bmob.test.BombUtil$9.done(BombUtil.java:331)
//            cn.bmob.v3.listener.QueryListener.done(QueryListener.java:9)
//            cn.bmob.v3.http.mine$This$27.accept(RxBmob.java:947)
//            io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:63)
//            io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:62)
//            io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:201)
//            io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:255)
//            io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:119)
//            android.os.Handler.handleCallback(Handler.java:790)
//            android.os.Handler.dispatchMessage(Handler.java:99)
//            android.os.Looper.loop(Looper.java:164)
//            android.app.ActivityThread.main(ActivityThread.java:6494)
//            java.lang.reflect.Method.invoke(Native Method)
//            com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
//            com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

    public static void remove(String funcname, Context context) {
        try {
            if (casts.containsKey(funcname)) {
                context.unregisterReceiver(casts.get(funcname));
                casts.remove(funcname);
                mapBuilder.get().remove(funcname);
            }
        } catch (Exception e) {

        }
    }


    public static void destroy(String place, Context context) {
        List list =
                ((ArrayList) namecontextmap.get(place));
        for (Object a : list) {
            remove(a.toString(), context);
            casts.remove(a.toString());
        }

    }

    public Intent intent(String funcname, Context context, MapBuilder mb, FunCallback funCallback) {
        return intent(funcname, "", context, mb, funCallback);
    }

    public Intent intent(String funcname, String task, Context context, MapBuilder mb, FunCallback funCallback) {
        Intent in = new Intent(funcname);
        for (Object o : mb.get().keySet()) {
            in.putExtra(o.toString(), mb.get().get(o).toString());
        }
        receive(funcname + "_result", task, context, funCallback);
        return in;
    }
}


// 除了有钱